# Copyright (C) Infiscape Corporation 2006

import math
import sys, os, os.path, time, traceback
pj = os.path.join

from PyQt4 import QtGui, QtCore, QtOpenGL
import ViewerBase

import osg2 as osg

from OpenSGTreeModel import OpenSGTreeModel

try:
   from OpenGL.GL import *
   from OpenGL.GLUT import *
   from OpenGL.GLU import *
except ImportError:
   app = QtGui.QApplication(sys.argv)
   QtGui.QMessageBox.critical(None, "textures.py",
                           "PyOpenGL must be installed to run this example.",
                           QtGui.QMessageBox.Ok | QtGui.QMessageBox.Default,
                           QtGui.QMessageBox.NoButton)
   sys.exit(app.exec_())


class GLWidget(QtOpenGL.QGLWidget):
   def __init__(self, parent = None, manager = None):
      opts = QtOpenGL.QGLFormat(QtOpenGL.QGL.DepthBuffer | QtOpenGL.QGL.AlphaChannel |
                                QtOpenGL.QGL.Rgba | QtOpenGL.QGL.DoubleBuffer)
      QtOpenGL.QGLWidget.__init__(self, opts, parent)

      f = self.format()
      print "Format: ", f
      print "   Depth: %s %s" % (f.depth(), f.depthBufferSize())
      print "   Alpha: %s %s " % (f.alpha(), f.alphaBufferSize())
      print "   Rgba: %s [%s, %s, %s, %s]" % (f.rgba(), f.redBufferSize(), f.greenBufferSize(), f.blueBufferSize(), f.alphaBufferSize())
      print "   Double: " , f.doubleBuffer()

      if manager is not None:
         self.mManager = manager
      else:
         self.mManager = osg.SimpleSceneManager()

      self.mTimer = QtCore.QTimer(self)
      self.connect(self.mTimer, QtCore.SIGNAL("timeout()"), self.updateGL)
      self.mTimer.start(0)

   def getManager(self):
      return self.mManager
    
   def minimumSizeHint(self):
      return QtCore.QSize(50, 50)
    
   def sizeHint(self):
      return QtCore.QSize(400, 400)
    
   def initializeGL(self):
      self.mManager.getWindow().init()
      glClearColor(0,0,0,0)
      glEnable(GL_DEPTH_TEST)
      glEnable(GL_CULL_FACE)
      glShadeModel(GL_SMOOTH)
    
   def paintGL(self):
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
      self.mManager.idle()
      self.mManager.redraw();

   def resizeGL(self, width, height):
      self.mManager.resize(width,height)
      glViewport(width/2,0,width,height);
    
   def mousePressEvent(self, event):
      print "OSGQGLManagedWidget::mousePressEvent()"
      if event.button() == QtCore.Qt.LeftButton:
         self.mManager.mouseButtonPress(osg.SimpleSceneManager.MouseLeft, event.x(), event.y())
      elif event.button() == QtCore.Qt.MidButton:
         self.mManager.mouseButtonPress(osg.SimpleSceneManager.MouseMiddle, event.x(), event.y())
      elif event.button() == QtCore.Qt.RightButton:
         self.mManager.mouseButtonPress(osg.SimpleSceneManager.MouseRight, event.x(), event.y())
      self.updateGL()

   def mouseReleaseEvent(self, event):
      print "OSGQGLManagedWidget::mouseReleaseEvent()"
      if event.button() == QtCore.Qt.LeftButton:
         self.mManager.mouseButtonRelease(osg.SimpleSceneManager.MouseLeft, event.x(), event.y())
      elif event.button() == QtCore.Qt.MidButton:
         self.mManager.mouseButtonRelease(osg.SimpleSceneManager.MouseMiddle, event.x(), event.y())
      elif event.button() == QtCore.Qt.RightButton:
         self.mManager.mouseButtonRelease(osg.SimpleSceneManager.MouseRight, event.x(), event.y())
      self.updateGL()
    
   def mouseMoveEvent(self, event):
      #print "Mouse move: ", (event.x(), event.y())
      self.mManager.mouseMove(event.x(), event.y())
      self.updateGL()

   def wheelEvent (self, we):
      print "OSGQGLManagedWidget::wheelEvent()"

      if we.delta() > 0:
         button = osg.SimpleSceneManager.MouseUp;
      else:
         button = osg.SimpleSceneManager.MouseDown;

      self.mManager.mouseButtonPress(button, we.x(), we.y())

      self.updateGL()

class Viewer(QtGui.QMainWindow, ViewerBase.Ui_MainWindow):
   def __init__(self, rootNode, glWidget, parent = None):
      QtGui.QMainWindow.__init__(self, parent)
      
      self.mGlWidget = glWidget
      
      self.setupUi(self)

      # Create tree view of OpenSG scene graph.
      self.mOpenSGTreeModel = OpenSGTreeModel(rootNode)
      self.treeView.setRootIsDecorated(True)
      self.treeView.setModel(self.mOpenSGTreeModel)
      root_index = self.treeView.rootIndex()

      # Register signal to highlight node.
      self.connect(self.treeView.selectionModel(),
         QtCore.SIGNAL("selectionChanged(QItemSelection,QItemSelection)"), self.onElementSelected)

   def setupUi(self, widget):
      ViewerBase.Ui_MainWindow.setupUi(self, widget)
      mainLayout = QtGui.QHBoxLayout()
      mainLayout.addWidget(self.mGlWidget)
      self.frame.setLayout(mainLayout)


   def onElementSelected(self, newSelection, oldSelection):
      #print "Current row: %s" % (self.mTreeView.currentIndex().row())
      if len(newSelection.indexes()) > 0:
         selected_element = self.treeView.model().data(newSelection.indexes()[0], QtCore.Qt.UserRole)
         print "Selected: %s" % (osg.getName(selected_element))
      else:
         selected_element = None

      self.mGlWidget.getManager().setHighlight(selected_element)
      self.mGlWidget.updateGL()


   def __tr(self,s,c = None):
      return qApp.translate("MainWindow",s,c)

def main():
   app = QtGui.QApplication(sys.argv)

   print "argv: ", sys.argv
   osg.osgInit([])
   pwin = osg.PassiveWindow.create()
   
   if len(sys.argv) < 2:
      print "Loading torus...."
      scene = osg.makeTorus(0.5,2,16,16)
      osg.setName(scene, "Root")
   else:
      scene = osg.SceneFileHandler.the().read(sys.argv[1])

   # Create and display GUI
   glWidget = GLWidget()
   v = Viewer(scene, glWidget)

   mgr = glWidget.getManager()
   mgr.setWindow(pwin)
   mgr.setRoot(scene)
   mgr.showAll()
   mgr.setStatistics(True)

   v.show()

   sys.exit(app.exec_())

if __name__ == '__main__':
   main()
